package com.liy.teaching.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liy.teaching.entity.ProductEntity;
import com.liy.teaching.mapper.ProductMapper;
import com.liy.teaching.service.ProductService;
import com.liy.teaching.util.JSONUtil;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;

/**
 * 布隆过滤器判断 不存在  准确率100%
 * 可以判断某样东西一定不存在
 *
 * 商品服务
 **/
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductEntity> implements ProductService {

    //前缀
    private static final String KEY_PREFIX = "product:";

    //  格式化一下
    private static String buildKey(String id) {
        return KEY_PREFIX + id;  // product:商品ID
    }



    @Resource(name = "redisTemplate")
    private ValueOperations<Serializable, String> redisOperations;


    @Autowired
    private RBloomFilter<String> redisBloomFilter;


    /**
     * 重载 getById(id)  做第一点增强
     *
     */
    @Override
    public ProductEntity getById(Serializable id) {

        String redisKey = buildKey(String.valueOf(id)); // 构建rediskey

        /*  1.如果这个 key  本来存在的  一定不会有判断失误

            2.如果这 key    本来不存在的  可能会判断失误   注意这里 把本来就不存在的 key 判断失误 ( 判断成了 存在 )
                                                       最多也就是多查一次数据库而已, 没有什么大问题, 失误率可以自己设置, 设置小一点 如 0.001
                                                       就可以挡住大部分的请求
        */
        if( redisBloomFilter.contains( redisKey ) ){   // 布隆过滤器判断 redisKey 是否存在

            String redisValue = redisOperations.get(redisKey);  // 从缓存中去查

            if (redisValue != null) {  // 查到了

                return JSONUtil.parseObject(redisValue, ProductEntity.class); //直接返回;

            } else { // 没查到
                ProductEntity product = getBaseMapper().selectById(id); // 从数据库中查, 然后放到缓存中;
                if(product !=null){
                    String jsonString = JSONUtil.toJSONString(product);
                    redisOperations.set(redisKey, jsonString);    // 放到缓存中

                    // redisOperations.set(redisKey, jsonString,1L, TimeUnit.DAYS);    // 放到缓存中

                    return product;
                }
                return null;
            }

        }



        return null;


    }

}
